//
//  SNetUtil.swift
//  niuguwang
//
//  Created by BrightLi on 2021/3/21.
//  Copyright © 2021年 taojinzhe. All rights reserved.
//

import Foundation
import CoreTelephony
import SystemConfiguration.CaptiveNetwork

public struct Platform {
    public static let isSimulator: Bool = {
        var isSim = false
        #if arch(i386) || arch(x86_64)
        isSim = true
        #endif
        return isSim
    }()
}

@objcMembers public class SNetUtil:NSObject
{
    public static let shared = SNetUtil()
    
    public var airPlance:Bool = false
    public var wifiEnabled:Bool = false
    public var wwanEnabled:Bool = false
    public var mobile:String = ""
    public var cellularState:CTCellularDataRestrictedState = .restrictedStateUnknown
    public var change:ChangeBlock?
    
    public lazy var reachability:SReachability? = {
        let result = try? SReachability(hostname: "www.apple.com")
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(reachabilityChanged(_:)),
            name:.reachabilityChanged,
            object: result
        )
        return result ?? nil
    }()
    
    // 是否已经断网
    dynamic public class var isDisnet:Bool{
        get{
            return shared.reachability?.connection == .unavailable
        }
    }
    // 是否为蜂窝网络
    dynamic public class var isWWAN:Bool{
        get{
            return shared.reachability?.connection == .cellular
        }
    }
    // WIFI是否开启
    dynamic public class var wifiEnabled:Bool{
        get{
            return shared.wifiEnabled
        }
    }
    
    // 是否wifi
    dynamic public class var isWifi:Bool{
        get{
        
            return shared.reachability?.connection == .wifi
        }
    }
    // 蜂窝网络是否开启
    dynamic public class var wwanEnabled:Bool{
        get{
            return shared.wwanEnabled
        }
    }
    
    dynamic public class func launch()
    {
        shared.launch()
    }
    
    dynamic func launch()
    {
        do {
            try reachability?.startNotifier()
        } catch {
            SLog.debug("连网状态通知失败")
        }
        if #available(iOS 9.0, *) {
            let call = CTCellularData()
            call.cellularDataRestrictionDidUpdateNotifier = {[unowned self] state in
                self.cellularState = state
                switch state{
                case .restricted:
                    SLog.debug("网络访问权限关闭")
                case .notRestricted:
                    SLog.debug("网络访问权限开启")
                case .restrictedStateUnknown:
                    SLog.debug("网络访问权限未知")
                default:
                    break
                }
            }
        }
    }
    
 
    // 连网状态改变
    dynamic public func reachabilityChanged(_ note: Notification)
    {
        if reachability?.connection == .cellular{
            wwanEnabled = true
            wifiEnabled = false
        }else if reachability?.connection == .wifi{
            wwanEnabled = false
            wifiEnabled = true
        }
        SLog.debug("info_net_change",netInfo())
        change?()
    }
    
    dynamic public class func netInfo()->String{
        return shared.netInfo()
    }
    
    dynamic func netInfo()->String
    {
        var log="互联网=\(reachability?.connection.description ?? "未知")"
        if airPlance{
            log+=",飞行模式=开启"
        }else if wwanEnabled{
            log+=",蜂窝"
        }
        if mobile.count>0 {
            log += ",运营商=\(mobile)"
        }
        let wifiName=SNetUtil.wifiName()
        if wifiEnabled{
            log+=",WIFI=\(wifiName)"
        }
        if wifiEnabled{
            if wifiName.count<1{
                print("wifi_name_error")
            }
        }
        return log
    }
    
    dynamic public class func showInfo()->String
    {
        var log=""
        if shared.airPlance{
            log="飞行模式"
        }else if shared.wwanEnabled{
            log="4G \(shared.mobile)"
        }else{
            let wifiName=SNetUtil.wifiName()
            log="WIFI \(wifiName)"
        }
        return log
    }
    
    dynamic public class func wifiName() -> String
    {
        let interfaces = CNCopySupportedInterfaces()
        var ssid = ""
        if interfaces != nil {
            let interfacesArray = CFBridgingRetain(interfaces) as! Array<AnyObject>
            if interfacesArray.count > 0 {
                let interfaceName = interfacesArray[0] as! CFString
                let ussafeInterfaceData = CNCopyCurrentNetworkInfo(interfaceName)
                if (ussafeInterfaceData != nil) {
                    let interfaceData = ussafeInterfaceData as! Dictionary<String, Any>
                    ssid = interfaceData["SSID"]! as! String
                }
            }
        }
        if ssid.count<1 && Platform.isSimulator{
            return "模拟器"
        }
        return ssid
    }
    
    dynamic public class func isTestWifi()->Bool{
        return SNetUtil.wifiName()=="ngw_test"
    }
    
    dynamic public class func localIP()->String
    {
        var addresses = [String]()
        var ifaddr : UnsafeMutablePointer<ifaddrs>? = nil
        if getifaddrs(&ifaddr) == 0 {
            var ptr = ifaddr
            while (ptr != nil) {
                let flags = Int32(ptr!.pointee.ifa_flags)
                var addr = ptr!.pointee.ifa_addr.pointee
                if (flags & (IFF_UP|IFF_RUNNING|IFF_LOOPBACK)) == (IFF_UP|IFF_RUNNING) {
                    if addr.sa_family == UInt8(AF_INET) || addr.sa_family == UInt8(AF_INET6) {
                        var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                        if (getnameinfo(&addr, socklen_t(addr.sa_len), &hostname, socklen_t(hostname.count),nil, socklen_t(0), NI_NUMERICHOST) == 0) {
                            if let address = String(validatingUTF8:hostname) {
                                addresses.append(address)
                            }
                        }
                    }
                }
                ptr = ptr!.pointee.ifa_next
            }
            freeifaddrs(ifaddr)
        }
        if addresses.count>0{
            return addresses.first!
        }
        return "unkown"
    }
    
    dynamic public class func mac()->String
    {
        var mac:String?
        if let interfaces:NSArray = CNCopySupportedInterfaces(){
            for sub in interfaces
            {
                if let dict = CFBridgingRetain(CNCopyCurrentNetworkInfo(sub as! CFString))
                {
                    mac = dict["BSSID"] as? String
                }
            }
        }
        return mac ?? "00:00:00:00:00:00"
    }
    // 清除缓存
    dynamic public class func clearCache(_ request:URLRequest)
    {
        URLCache.shared.removeCachedResponse(for: request)
        if let _ = URLCache.shared.cachedResponse(for: request)
        {
            SLog.debug("清理缓存失败:%@",request.url!.absoluteString)
            URLCache.shared.removeAllCachedResponses()
        }else{
            SLog.debug("清理缓存成功:%@",request.url!.absoluteString)
        }
    }
}
